package com.sc.service.calculate;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

@Service
public class CalculationService {

    // 中文变量名到英文变量名的映射
    private static final Map<String, String> VARIABLE_MAPPING = new HashMap<>();
    static {
        VARIABLE_MAPPING.put("仪表量", "usage");
        VARIABLE_MAPPING.put("单价", "unitPrice");
    }

    /**
     * 根据公式和精度计算总价
     *
     * @param formula 计算公式
     * @param variables 公式中的变量值
     * @param precision 计算精度
     * @return 计算结果
     */
    public BigDecimal calculateTotalAmount(String formula, Map<String, Object> variables, BigDecimal precision) {
        // 创建 SpEL 解析器
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();

        // 将中文变量名替换为英文变量名
        Map<String, Object> mappedVariables = new HashMap<>();
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
            String englishVariable = VARIABLE_MAPPING.get(entry.getKey());
            if (englishVariable != null) {
                mappedVariables.put(englishVariable, entry.getValue());
            }
        }

        // 将变量添加到上下文
        mappedVariables.forEach(context::setVariable);

        // 替换公式中的中文变量名为英文变量名
        String processedFormula = formula;
        for (Map.Entry<String, String> entry : VARIABLE_MAPPING.entrySet()) {
            processedFormula = processedFormula.replace(entry.getKey(), entry.getValue());
        }

        // 处理公式：为变量名添加 #
        processedFormula = FormulaUtils.addHashToVariables(processedFormula, mappedVariables);

        // 解析并计算表达式
        Expression expression = parser.parseExpression(processedFormula);
        BigDecimal result = expression.getValue(context, BigDecimal.class);

        // 根据精度四舍五入
        return result.divide(precision, 0, RoundingMode.HALF_UP).multiply(precision);
    }
}
